home *** CD-ROM | disk | FTP | other *** search
- /* hAWK_recurse.c -- could have been called hAWK_hAWK.c,
- implements the hAWK() function which allows hAWK to call itself.
-
- Ala MultiFinder, variables with more than function scope are saved
- and restored.
- */
- /* Copyright © 1986, 1988, 1989 1991 the Free Software Foundation, Inc.
- * This file is part of GAWK, the GNU implementation of the
- * AWK Progamming Language, modified for the Macintosh (also called hAWK).
- * GAWK is free software; you can redistribute or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 1, or any later version.
- * GAWK is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- * You should have received a copy of the GNU General Public License
- * along with GAWK; see the file "COPYING hAWK". If not, write to
- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
- * Written for THINK C 4 on the Macintosh by Ken Earle (Dynabyte) Aug 1991.
- */
- #include "AWK.H"
-
- /* If KEEPGOING is defined, execution will continue even if an error
- occurs during hAWK() call that would be fatal in the main call. */
- /*#define KEEPGOING */
-
- /* An instance of the HAWKstate struct is created for each recursive
- call to hAWK - it stores the state of the calling instance, for
- restoration afterwards. This is an ugly but effective way of treating
- global variables as local by stacking them up. */
- HAWKstatePtr hs = NULL;
-
- /* This (new) global variable allows the main hAWK routine to
- determine if it is being called for the first time or not
- - less initialization is done for second and subsequent calls. */
- short hAWKstackDepth = 0;
-
- /* from ARRAY.C */
- extern struct search *assoc_scan_sort(NODE *symbol);
- extern struct search *assoc_next_sort(struct search *lookat);
- /* from AWK_MAIN.C */
- extern short AWKmain(short argc, char **argv);
-
- /* hAWK_recurse.c functions */
- NODE *do_hAWK(NODE *tree);
- char **SetUpARGV(short *argcPtr, NODE *arr);
- void SaveHAWKstate(void);
- void RestoreHAWKstate(void);
-
- /* Save current state, start hAWK over, restore state, return
- integer representing success(1) or failure(0).
- First and only argument is argv[] node array. argc is calculated.
- WARNING argv[] passed must be a user variable - fiddling with
- built-in ARGV and trying to pass it will not work?
- */
- NODE *do_hAWK(NODE *tree)
- {
- HAWKstatePtr tempHSPtr;
- NODE *t1, *arr;
- short argc, result;
- char **argv;
-
-
- /* retrieve argument argv[] node */
- if (!tree) {
- fatal("hAWK requires at least one argument");
- }
- t1 = tree->lnode;
- arr = t1;
- if (t1->type == Node_param_list)
- arr = stack_ptr[t1->param_cnt];
- if (arr->type != Node_var && arr->type != Node_var_array)
- fatal("second argument of hAWK is not a variable");
- argv = SetUpARGV(&argc, arr);
- if (!argv)
- {
- fatal("argument of hAWK is indecipherable");
- }
- /* allocate new HAWKstate */
- emalloc(tempHSPtr, HAWKstatePtr, sizeof(HAWKstate), "hAWK");
- tempHSPtr->onebefore = hs;
- hs = tempHSPtr;
- ++hAWKstackDepth;
- SaveHAWKstate();
- #ifdef KEEPGOING
- if (!setjmp(envBuf))
- {
- AWKmain(argc, argv);
- RestoreHAWKstate();
- result = hAWKstackDepth;
- }
- else
- {
- RestoreHAWKstate();
- SysBeep(2);
- result = 0;
- }
- #else
- AWKmain(argc, argv);
- RestoreHAWKstate();
- result = hAWKstackDepth;
- #endif
- tempHSPtr = hs;
- hs = hs->onebefore;
- free(tempHSPtr);
- free(argv);
- --hAWKstackDepth;
- return tmp_number((AWKNUM)result);
- }
-
-
- char **SetUpARGV(short *argcPtr, NODE *arr)
- {
- char *temp, **argv;
- short argc = 0, numNull = 0;
- struct search *l;
- long j, k;
-
- /* determine argument count; this is a bit tricky since a program
- may reuse an array to call "hAWK" repeatedly, and the array may
- shrink; as a crude rule, ten null entries in a row is taken to
- mean there are no more entries. */
- for (j = 0; j < 5000; ++j)
- {
- temp =
- force_string(*assoc_lookup(arr, tmp_number((AWKNUM) (j))))->stptr;
- ++argc;
- if (*temp)
- numNull = 0;
- else
- {
- ++numNull;
- if (numNull > 9)
- {
- argc -= numNull;
- break;
- }
- }
- }
- if (argc == 0)
- return(NULL);
-
- /* allocate argv[] */
- emalloc(argv, char **, argc * sizeof(char *), "SetUpARGV");
- /* fill argv[]: retrieve elements indexed 0 to argc-1 */
- for (j = 0, k = argc; j < k; ++j)
- {
- argv[j] =
- force_string(*assoc_lookup(arr, tmp_number((AWKNUM) (j))))->stptr;
- }
- *argcPtr = argc;
- return(argv);
- }
-
- void SaveHAWKstate()
- {
- extern void SaveCommonsInAwkH(void);
- extern void SaveAwkTabVars(void);
- extern void SaveEval(void);
- extern void SaveField(void);
- extern void SaveIO(void);
- extern void SaveNode(void);
- extern void SaveRegex(void);
-
- #ifdef KEEPGOING
- BlockMove((Ptr)envBuf, (Ptr)(hs->envBuf), sizeof(jmp_buf));
- #endif
- SaveCommonsInAwkH();
- SaveAwkTabVars();
- SaveEval();
- SaveField();
- SaveIO();
- SaveNode();
- SaveRegex();
- }
-
- void RestoreHAWKstate()
- {
- extern void RestoreCommonsInAwkH(void);
- extern void RestoreAwkTabVars(void);
- extern void RestoreEval(void);
- extern void RestoreField(void);
- extern void RestoreIO(void);
- extern void RestoreNode(void);
- extern void RestoreRegex(void);
-
- #ifdef KEEPGOING
- BlockMove((Ptr)(hs->envBuf), (Ptr)envBuf, sizeof(jmp_buf));
- #endif
- RestoreCommonsInAwkH();
- RestoreAwkTabVars();
- RestoreEval();
- RestoreField();
- RestoreIO();
- RestoreNode();
- RestoreRegex();
- }
-